package edu.hda.pt.client;

import java.util.Vector;

import edu.hda.pt.client.connections.PTClientMINA;
import edu.hda.pt.client.connections.PTClientNetty;
import edu.hda.pt.client.connections.PTClientRMI;
import edu.hda.pt.client.connections.PTClientXSocket;
import edu.hda.pt.utils.ConnectionMethod;
import edu.hda.pt.utils.Datatype;
import edu.hda.pt.utils.Logger;
import edu.hda.pt.utils.TestMethod;

/**
 * RunPTClient is the main class for running the client
 * 
 * @author Marc Hammerton
 * 
 */
public class RunPTClient {

	/**
	 * Main method for running the test clients. First the factors are set and
	 * then the method runTests is called to conduct the performance tests.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		String serverIP = "127.0.0.1";
		Logger.logg2File = false;
		PTClient.test2run = TestMethod.RTT;
		PTClient.datatype = Datatype.OBJECT;
		PTClient.datasize = 1024; // { 10, 100,1024}

		RunPTClient runPTClient;

		ConnectionMethod connectionMethod = ConnectionMethod.XSOCKET; // { MINA,
		// NETTY,
		// RMI,
		// XSOCKET}
		PTClient.stream_fs = Config.STREAM_FS[2]; // { 20480, 40960, 81920,
		// 204800}
		Config.NR_CLIENTS[0] = 1; // { 1, 10, 30, 70, 100}

		runPTClient = new RunPTClient();
		runPTClient.runTests(connectionMethod, serverIP);
		System.out.println(" +++++++++++ Test finished +++++++++++");

	}

	/**
	 * Default constructor
	 */
	public RunPTClient() {
	}

	/**
	 * The method runTests creates the clients and then starts the threads for
	 * the tests. It waits for all tests to be completed and logs the results.
	 * 
	 * @param connectionMethod - The connection method for this test
	 * @param serverIP - The IP address of the server
	 */
	public void runTests(ConnectionMethod connectionMethod, String serverIP) {

		Vector<Thread> clientsThreads;
		PTClient[] clients;

		for (int nrOfClients : Config.NR_CLIENTS) {
			clientsThreads = new Vector<Thread>();
			clients = new PTClient[nrOfClients];

			// Create Clients
			for (int i = 0; i < clients.length; i++) {
				switch (connectionMethod) {
					case RMI:
						clients[i] = new PTClientRMI(serverIP);
						break;
					case MINA:
						clients[i] = new PTClientMINA(serverIP);
						break;
					case NETTY:
						clients[i] = new PTClientNetty(serverIP);
						break;
					case XSOCKET:
						clients[i] = new PTClientXSocket(serverIP);
						break;
					default:
						System.out.println("no connection method selected");
						break;
				}

				clients[i].clientID = "client_" + (i + 1);
				clientsThreads.add(new Thread(clients[i]));
			}

			// Start client threads
			for (Thread clientThread : clientsThreads) {
				clientThread.start();
			}

			// Wait for tests to be finished
			try {

				for (Thread clientThread : clientsThreads) {
					clientThread.join();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			// Log results
			for (PTClient client : clients) {
				Logger.logTestResults(client.clientID, client.results,
						serverIP, connectionMethod, nrOfClients);
			}
			Logger.closeFile();

			switch (PTClient.test2run) {
				case STREAMING:
					Logger.printStreamResults();
					break;
				case TP:
					Logger.printThroughput();
					break;
				case RTT:
					Logger.printTestRTT();
					break;
				case TESTTIME:
					Logger.printTestTimes();
					break;
			}

			System.out.println(nrOfClients + " finished");
		}
	}

}
